package org.bdware.irs.server.http;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import org.rocksdb.Options;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

public class LocalHandler extends RegisterHandler{

    RocksDB db;
    String dbPath = "./handleRecords/";

    static {
        RocksDB.loadLibrary();
    }
    public LocalHandler(){
        Options rockopts = new Options().setCreateIfMissing(true);
        try {
            System.out.println("[The actual rocksdb path:] " + new File(dbPath).getAbsolutePath());
            db = RocksDB.open(rockopts, dbPath);
        } catch (RocksDBException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @Override
    public Map<String, String> HandleRequest(Map<String, String> postInfo) {
        Map<String,String> respMap = new HashMap<>();
        String action = postInfo.get("action");
        switch (action){
            case "resolve":
                respMap = handleResolve(postInfo);
                break;
            case "register":
            case "forceRegister":
                try {
                    respMap = handleRegister(postInfo);
                } catch (RocksDBException e) {
                    e.printStackTrace();
                    respMap.put("status","0");
                    respMap.put("response","respond failed from LHS");
                }
                break;
            case "unregister":
            case "forceDelete":
                respMap = handleUnRegister(postInfo);
                break;
            case "reregister":
                respMap = handleReregister(postInfo);
                break;
            default:
                System.out.println("error response");
        }
        return respMap;
    }
    public Map<String,String> handleRegister(Map<String,String> reqMap) throws RocksDBException {
        Map<String,String> respMap = new HashMap<>();
        String prefix;
        switch (reqMap.get("hrType")){
            case "do":
                prefix = "do.";
                break;
            case "dou":
                prefix = "dou.";
                break;
            case "org/bdware/doip":
                prefix = "doip.";
                break;
            default:
                prefix = "ukw.";
                break;
        }
        reqMap.remove("action");
        reqMap.remove("hrType");
        String randomBase = geneRandomID();
        String identifier = "86.5000.470/" + prefix + randomBase+"_bdw";
        while(db.get(identifier.getBytes())!=null){
            randomBase = geneRandomID();
            identifier = "86.5000.470/" + prefix + randomBase+"_bdw";
        }
        if(reqMap.get("count")!= null){
            int count = Integer.parseInt(reqMap.get("count"));
            reqMap.remove("count");
            reqMap.put("identifier",identifier);
            String handleRecord = new Gson().toJson(reqMap);
            db.put(identifier.getBytes(),handleRecord.getBytes());
            JsonArray ids = new JsonArray();
            ids.add(identifier);
            for(int i=1;i<count;i++){
                identifier = "86.5000.470/" + prefix + randomBase + "_" + i + "_bdw";
                reqMap.put("identifier",identifier);
                handleRecord = new Gson().toJson(reqMap);
                db.put(identifier.getBytes(),handleRecord.getBytes());
                ids.add(identifier);
            }
            respMap.put("identifier",new Gson().toJson(ids));
            respMap.put("status","1");
            respMap.put("response","register DO success, count: "+ count);
        }else{
            reqMap.put("identifier",identifier);
            String handleRecord = new Gson().toJson(reqMap);
            db.put(identifier.getBytes(),handleRecord.getBytes());
            System.out.println("successful update do, identifier: "+identifier);
            respMap.put("identifier",identifier);
            respMap.put("status","1");
            respMap.put("response","register DO success, identifier: "+ identifier);
        }
        return respMap;
    }

    public Map<String,String> handleReregister(Map<String,String> reqMap){
        Map<String,String> respMap = new HashMap<>();
        String identifier;
        if (reqMap.get("identifier") != null) identifier = reqMap.get("identifier");
        else{
            respMap.put("status","0");
            respMap.put("response","identifier not found");
            return respMap;
        }
        try {
            reqMap.remove("action");
            reqMap.remove("hrType");
            String handleRecord = new Gson().toJson(reqMap);
            db.delete(identifier.getBytes());
            db.put(identifier.getBytes(),handleRecord.getBytes());
            System.out.println("successful update do, identifier: "+identifier);
            respMap.put("identifier",identifier);
            respMap.put("status","1");
            respMap.put("response","reRegister DO success, identifier: "+ identifier);
        } catch (Exception e) {
            e.printStackTrace();
            respMap.put("status","0");
            respMap.put("response","unregister failed: " + e.getMessage());
        }
        return respMap;
    }

    public Map<String,String> handleUnRegister(Map<String,String> reqMap){
        Map<String,String> respMap = new HashMap<>();
        String identifier;
        if (reqMap.get("identifier") != null) identifier = reqMap.get("identifier");
        else{
            respMap.put("status","0");
            respMap.put("response","identifier not found");
            return respMap;
        }
        try {
            db.delete(identifier.getBytes());
            respMap.put("status","1");
            respMap.put("response","success delete: " + identifier);
        } catch (Exception e) {
            e.printStackTrace();
            respMap.put("status","0");
            respMap.put("response","unregister failed: " + e.getMessage());
        }
        return respMap;
    }

    public Map<String,String> handleResolve(Map<String,String> reqMap){
        Map<String,String> respMap = new HashMap<>();
        String identifier;
        if (reqMap.get("identifier") != null) identifier = reqMap.get("identifier");
        else{
            respMap.put("status","0");
            respMap.put("response","identifier not found");
            return respMap;
        }
        try{
            if(db.get(identifier.getBytes()) == null){
                respMap.put("status","0");
                respMap.put("response","not exist");
                return respMap;
            }
            String result = new String(db.get(identifier.getBytes()));
            respMap = new Gson().fromJson(result,HashMap.class);
        }catch (Exception e){
            e.printStackTrace();
            respMap.put("status","0");
            respMap.put("response","resolve failed: " + e.getMessage());
        }
        return respMap;
    }
}

